<template>
  <div>
    <a-modal
      title="表单配置"
      :visible="visible"
      :confirmLoading="confirmLoading"
      @ok="ok"
      @cancel="cancel"
      :maskClosable="false"
    >
      <template v-if="isError">
        <div class="empty-wrap">
          <a-empty :description="description" />
        </div>
      </template>
      <template v-else>
        <div class="form-header">
          <div class="form-name">
            表单名称：
            <span
              ><a-tag color="#2db7f5">{{ formName }}</a-tag></span
            >
          </div>
        </div>
        <div class="line"></div>
        <a-spin :spinning="spinning" :tip="tip">
          <a-table
            class="item-table"
            :columns="columns"
            :dataSource="table"
            :scroll="{ y: 300 }"
            :pagination="false"
          >
            <span slot="customTitle">批量全选</span>
            <span slot="customLook">
              <a-checkbox
                v-model="allLook"
                :indeterminate="lookIndeterminate"
                @change="onChangeLookAll"
              >
                可查看
              </a-checkbox>
            </span>
            <span slot="customEdit">
              <a-checkbox
                v-model="allEdit"
                :disabled="allDisabled"
                :indeterminate="editIndeterminate"
                @change="onChangeEditAll"
              >
                可编辑
              </a-checkbox>
            </span>
            <span slot="look" slot-scope="text, record, index">
              <a-checkbox
                v-model="record.look"
                @change="(event) => onChangeLook(event, index, record)"
              >
                可查看
              </a-checkbox>
            </span>
            <span slot="edit" slot-scope="text, record, index">
              <a-checkbox
                v-model="record.edit"
                :disabled="!record.look"
                @change="(event) => onChangeEdit(event, index)"
              >
                可编辑
              </a-checkbox>
            </span>
          </a-table>
        </a-spin>
      </template>
    </a-modal>
  </div>
</template>

<script>
import { getFormDetail, getTableConfig } from "./helper/index"

const columns = [
  {
    dataIndex: "name",
    ellipsis: true,
    key: "name",
    slots: { title: "customTitle" },
  },
  {
    dataIndex: "look",
    key: "look",
    width: 90,
    slots: { title: "customLook" },
    scopedSlots: { customRender: "look" },
  },
  {
    dataIndex: "edit",
    key: "edit",
    width: 90,
    slots: { title: "customEdit" },
    scopedSlots: { customRender: "edit" },
  },
];
export default {
  props: {
    initChecked: {
      type: Boolean,
      default: false,
    }
  },
  computed: {
    isError() {
      return !!this.error;
    },
    formName() {
      const formDetail = this.formDetail;
      if (formDetail?.formBasicConfigure?.name) {
        return formDetail?.formBasicConfigure?.name;
      }
      return "未知表单";
    },
    allDisabled() {
      const allLook = this.allLook;
      return !allLook;
    },
  },
  data() {
    return {
      visible: false,
      form: this.$form.createForm(this),
      error: false,
      description: "未知错误",
      formItems: [],
      formDetail: {}, // 存储表单信息
      columns,
      table: [],
      allLook: false, // 是否全选可查看
      allEdit: false, // 是否全选可编辑
      lookIndeterminate: false, // 可查看是否半选
      editIndeterminate: false, // 可编辑是否半选
      checkedLook: [], // 已选择的可查看
      checkedEdit: [], // 已选择的可编辑
      spinning: false,
      tip: "更新配置中",
      confirmLoading: false,
      openConfig: null, // 打开配置时的配置
    };
  },
  methods: {
    ok() {
      getTableConfig(this.table).then(config => {
        this.$emit("ok", config);
        this.changeVisible(false);
      }).catch(error => {
        this.$message.error(error.message || "操作失败");
      })
    },
    cancel() {
      this.$emit("cancel");
      this.changeVisible(false);
    },
    openModal(config) {
      this.changeVisible(true);
      this.openConfig = config;
      this.loadConfig(config);
    },
    changeVisible(visible) {
      this.visible = visible;
    },
    loadConfig(config) {
      if (config && config.formUuid) {
        this.setPageError(false, "");
        this.formItems = [];
        getFormDetail(config.formUuid, this.initChecked, config.formItemConfigs).then((result) => {
          const {
            formItems,
            formDesign,
            checkedLook,
            checkedEdit,
          } = result;
          this.formItems = formItems;
          this.formDetail = formDesign;
          this.checkedLook = checkedLook;
          this.checkedEdit = checkedEdit;
          this.loadTable();
        }).catch((error) => {
          this.setPageError(true, "配置加载失败请检查配置项");
        });
      } else {
        this.setPageError(true, "配置加载失败请检查配置项");
      }
    },
    setPageError(error, description) {
      this.error = error;
      this.description = description;
    },
    // 加载表格
    loadTable() {
      // 初始化表格数据
      this.tip = "加载数据中";
      this.updateItemLoading(true);
      const initChecked = this.initChecked;
      const list = this.formItems
      setTimeout(() => {
        // this.table = Array.from({ length: 1000 }, (index) => ({ ...list[0] }));
        this.table = list;
        this.lookIndeterminate = false;
        this.editIndeterminate = false;
        if(this.openConfig?.formItemConfigs) {
          this.updateLookCheckAll();
          this.updateEditCheckAll();
        }else{
          this.allEdit = initChecked;
          this.allLook = initChecked;
        }
        this.updateItemLoading(false);
      }, 1000)
    },
    onChangeLookAll(event) {
      const checked = event.target.checked;
      const lookIndeterminate = this.lookIndeterminate;
      this.tip = "更新配置中";
      this.updateItemLoading(true);
      // 当半选被选中时点击全选为全选处理
      if (lookIndeterminate) {
        this.allLook = checked;
        this.lookIndeterminate = false;
        setTimeout(() => {
          this.batchUpdate("look", checked).then((res) => {
            this.updateItemLoading(false);
          });
        }, 400);
      } else {
        setTimeout(() => {
          if(!checked) {
            this.allEdit = false;
            this.editIndeterminate = false;
            this.checkedEdit = [];
          }
          this.batchUpdate("look", checked).then((res) => {
            this.updateItemLoading(false);
          });
        }, 400);
        if (checked) {
          this.checkedLook = this.table.map((item, index) => index);
        } else {
          this.checkedLook = [];
        }
      }
    },
    onChangeEditAll(event) {
      const checked = event.target.checked;
      const editIndeterminate = this.editIndeterminate;
      this.updateItemLoading(true);
      // 当半选被选中时点击全选为全选处理
      if (editIndeterminate) {
        this.allEdit = checked;
        this.editIndeterminate = false;
        setTimeout(() => {
          this.batchUpdate("edit", checked).then((res) => {
            this.updateItemLoading(false);
          })
        })
      }else{
        setTimeout(() => {
          this.batchUpdate("edit", checked).then((res) => {
            this.updateItemLoading(false);
          })
        })
        if (checked) {
          this.checkedEdit = this.table.map((item, index) => index);
        }else {
          this.checkedEdit = [];
        }
      }
    },
    onChangeLook(event, index, record) {
      const checked = event.target.checked;
      if (checked) {
        this.checkedLook.push(index);
      } else {
        const findIndex = this.checkedLook.findIndex((item) => item === index);
        if (findIndex > -1) {
          this.checkedLook.splice(findIndex, 1);
        }
        this.onChangeEdit(event, index);
        record.edit && (record.edit = false);
      }
      this.updateLookCheckAll();
    },
    onChangeEdit(event, index) {
      const checked = event.target.checked;
      if (checked) {
        this.checkedEdit.push(index);
      } else {
        const findIndex = this.checkedEdit.findIndex((item) => item === index);
        if (findIndex > -1) {
          this.checkedEdit.splice(findIndex, 1);
        }
      }
      this.updateEditCheckAll();
    },
    updateLookCheckAll() {
      this.allLook =
        this.checkedLook.length > 0 &&
        this.checkedLook.length === this.table.length;
      this.lookIndeterminate =
        this.checkedLook.length > 0 &&
        this.checkedLook.length < this.table.length;
    },
    updateEditCheckAll() {
      this.allEdit =
        this.checkedEdit.length > 0 &&
        this.checkedEdit.length === this.table.length;
      this.editIndeterminate =
        this.checkedEdit.length > 0 &&
        this.checkedEdit.length < this.table.length;
    },
    // 当数据量过大时 批次更新
    batchUpdate(editType = "look", updateType = false) {
      return new Promise((resolve, reject) => {
        const table = this.table;
        if(table.length > 40) {
          this.batchUpdateItem(editType, updateType).then(() => {
            resolve();
          })
        }else{
          for (let index = 0; index < table.length; index++) {
            const element = table[index];
            element[editType] = updateType;
            if(editType === "look" && !updateType) {
              element.edit = false;
            }
          }
          resolve();
        }
      });
    },
    batchUpdateItem(editType = "look", updateType = false) {
      return new Promise((resolve, reject) => {
        const table = this.table;
        const size = 15;
        let pageNo = 1;
        const updateBatch = () => {
          const start = (pageNo - 1) * size;
          const end =
            pageNo * size >= table.length ? table.length : pageNo * size;
          try {
            for (let index = start; index < end; index++) {
              const element = table[index];
              element[editType] = updateType;
              if(editType === "look" &&!updateType) {
                element.edit = false;
              }
            }
            this.$nextTick(() => {
              if (end < table.length) {
                pageNo++;
                setTimeout(updateBatch, 10);
              } else {
                resolve(); // 所有批次更新完成，resolve 该 Promise
              }
            });
          } catch (error) {
            reject(error); // 出错时 reject 该 Promise
          }
        };
        updateBatch();
      })
    },
    updateItemLoading(spinning) {
      this.spinning = spinning;
      this.confirmLoading = spinning;
    },
  },
};
</script>

<style lang="scss" scoped>
.line {
  margin-top: 20px;
}
.item-table /deep/ .ant-table-thead > tr > th,
.item-table /deep/ .ant-table-tbody > tr > td {
  padding: 10px;
}
</style>